package com.wmada.spring.service.impl;

import com.timerchina.base.ActionResult;
import com.timerchina.base.FailureActionResult;
import com.timerchina.base.SuccessActionResult;
import com.timerchina.toolkit.time.DateUtils;
import com.timerchina.toolkit.type.ValidateUtils;
import com.wmada.spring.bean.User;
import com.wmada.spring.dao.UserRepository;
import com.wmada.spring.service.UserService;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import javax.persistence.EntityNotFoundException;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * @author will.ma
 * @date 2020-9-29
 */
@Service("userService")
@ConfigurationProperties(prefix = "com.wmada.user")
public class UserServiceImpl implements UserService {

    private final UserRepository userRepository;

    private int  freezeFailureTimes;
    private int  freezeTimeInMilliseconds;
    private Date frozenTime;
    private Date unFrozenTime;

    public UserServiceImpl(UserRepository userRepository) {this.userRepository = userRepository;}

    public User get(Long id) {
        Optional<User> userOptional = userRepository.findById(id);
        if (userOptional.isPresent()) {
            return userOptional.get();
        } else {
            throw new EntityNotFoundException();
        }
    }

    @Override
    public ActionResult<User> add(User user) {
        ActionResult<Void> check = duplicate(user);
        if (check.isOk()) {
            return new SuccessActionResult<>(userRepository.save(user));
        } else {
            return new FailureActionResult<>(check.getMessage());
        }
    }

    @Override
    public User update(User user) {
        return userRepository.save(user);
    }

    @Override
    public void delete(User user) {
        userRepository.delete(user);
    }

    public List<User> list() {
        return userRepository.findAll();
    }

    public Page<User> list(int page, int pageSize) {
        return userRepository.findAll(PageRequest.of(page, pageSize));
    }

    public User getUserById(Long id) {
        Optional<User> userOptional = userRepository.findById(id);
        return userOptional.orElse(null);
    }

    public User getUserByUsername(String username) {
        return userRepository.findByUsername(username);
    }

    public User getUserByEmail(String emailAddress) {
        return userRepository.findByEmail(emailAddress);
    }

    public User getUserByPhone(String phoneNumber) {
        return userRepository.findByPhone(phoneNumber);
    }

    public ActionResult<User> changePassword(@NotNull User user, @NotBlank String oldPassword, @NotBlank String newPassword) {
        if (user == null) {
            return new FailureActionResult<>("用户不能为空");
        }
        if (user.valid(oldPassword)) {
            if (oldPassword.equals(newPassword)) {
                return new FailureActionResult<>("新旧密码不能相同");
            }

            resetPassword(user, newPassword);

            return new SuccessActionResult<>(user);
        } else {
            return new FailureActionResult<>("原密码错误");
        }
    }

    public void resetPassword(User user, String password) {
        user.resetPassword(password);
        userRepository.save(user);
    }

    public void updateLoginFailure(User user) {
        long now = System.currentTimeMillis();
        if (user.getFailureTimes() >= freezeFailureTimes - 1) {
            long lockTillTime = now + freezeTimeInMilliseconds;
            user.setFailureTimes(0);
            user.setLastLoginTime(new Date(now));
            user.setLockTillTime(new Date(lockTillTime));
        } else {
            user.setFailureTimes(user.getFailureTimes() + 1);
            user.setLastLoginTime(new Date(now));
        }
        userRepository.save(user);
    }

    public void updateLoginSuccess(User user) {
        Date now = DateUtils.getNow();
        user.setFailureTimes(0);
        user.setLastLoginTime(now);
        userRepository.save(user);
    }

    public void freeze(User user, boolean isFrozen) {
        user.setLockTillTime(isFrozen ? frozenTime : unFrozenTime);
        userRepository.save(user);
    }

    public ActionResult<Void> duplicate(User user) {
        if (user.getId() == null) {
            User userWithSameUsername = userRepository.findByUsername(user.getUsername());
            if (userWithSameUsername != null) {
                return new FailureActionResult<>("该用户名已存在");
            }
            if (ValidateUtils.notEmpty(user.getEmail())) {
                User userWithSameEmail = userRepository.findByEmail(user.getEmail());
                if (userWithSameEmail != null) {
                    return new FailureActionResult<>("该邮箱已存在");
                }
            }
            if (ValidateUtils.notEmpty(user.getPhone())) {
                User userWithSamePhone = userRepository.findByPhone(user.getPhone());
                if (userWithSamePhone != null) {
                    return new FailureActionResult<>("该手机号已存在");
                }
            }
        } else {
            if (ValidateUtils.notEmpty(user.getEmail())) {
                User userWithSameEmail = userRepository.findByEmailAndIdNot(user.getEmail(), user.getId());
                if (userWithSameEmail != null) {
                    return new FailureActionResult<>("该邮箱已存在");
                }
            }
            if (ValidateUtils.notEmpty(user.getPhone())) {
                User userWithSamePhone = userRepository.findByPhoneAndIdNot(user.getPhone(), user.getId());
                if (userWithSamePhone != null) {
                    return new FailureActionResult<>("该手机号已存在");
                }
            }
        }
        return new SuccessActionResult<>();
    }

}
